package datastructure.circularqueue;

/**
 * @Author ZhangCuirong
 * @Date 2025/7/29 15:04
 * @description:
 */
public class CircularQueue<E> {
    // 存储队列元素的数组
    private Object[] elements;
    // 队列容量
    private int capacity;
    // 队头指针，指向队头元素
    private int front;
    // 队尾指针，指向队尾元素的下一个位置
    private int rear;
    // 队列中元素的数量
    private int size;

    /**
     * 构造方法，初始化循环队列
     * @param capacity 队列的容量
     */
    public CircularQueue(int capacity) {
        if (capacity <= 0) {
            throw new IllegalArgumentException("队列容量必须大于0: " + capacity);
        }
        this.capacity = capacity;
        // 为了区分队列满和空的状态，实际容量比指定容量大1
        this.elements = new Object[capacity + 1];
        this.front = 0;
        this.rear = 0;
        this.size = 0;
    }

    /**
     * 入队操作
     * @param element 要加入队列的元素
     * @return 入队成功返回true，队列满则返回false
     */
    public boolean enqueue(E element) {
        if (isFull()) {
            return false;
        }
        elements[rear] = element;
        // 循环移动尾指针
        rear = (rear + 1) % elements.length;
        size++;
        return true;
    }

    /**
     * 出队操作
     * @return 出队的元素，如果队列为空则返回null
     */
    @SuppressWarnings("unchecked")
    public E dequeue() {
        if (isEmpty()) {
            return null;
        }
        E element = (E) elements[front];
        // 循环移动头指针
        front = (front + 1) % elements.length;
        size--;
        return element;
    }

    /**
     * 获取队头元素，但不出队
     * @return 队头元素，如果队列为空则返回null
     */
    @SuppressWarnings("unchecked")
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return (E) elements[front];
    }

    /**
     * 判断队列是否为空
     * @return 队列为空返回true，否则返回false
     */
    public boolean isEmpty() {
        return front == rear;
    }

    /**
     * 判断队列是否已满
     * @return 队列满返回true，否则返回false
     */
    public boolean isFull() {
        // 尾指针的下一个位置是头指针时，表示队列已满
        return (rear + 1) % elements.length == front;
    }

    /**
     * 获取队列中元素的数量
     * @return 队列中元素的数量
     */
    public int size() {
        return size;
    }

    /**
     * 获取队列的容量
     * @return 队列的容量
     */
    public int capacity() {
        return capacity;
    }

    /**
     * 清空队列
     */
    public void clear() {
        front = 0;
        rear = 0;
        size = 0;
        // 可选：清空元素，帮助垃圾回收
        for (int i = 0; i < elements.length; i++) {
            elements[i] = null;
        }
    }

    /**
     * 重写toString方法，用于打印队列内容
     * @return 队列的字符串表示
     */
    @Override
    public String toString() {
        if (isEmpty()) {
            return "[]";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        int index = front;
        while (index != rear) {
            sb.append(elements[index]);
            index = (index + 1) % elements.length;
            if (index != rear) {
                sb.append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    // 测试方法
    public static void main(String[] args) {
        CircularQueue<Integer> queue = new CircularQueue<>(5);

        // 入队测试
        for (int i = 1; i <= 5; i++) {
            queue.enqueue(i);
        }
        System.out.println("入队5个元素后: " + queue); // 应该输出 [1, 2, 3, 4, 5]
        System.out.println("队列是否已满: " + queue.isFull()); // 应该输出 true

        // 尝试入队第6个元素
        boolean result = queue.enqueue(6);
        System.out.println("尝试入队第6个元素是否成功: " + result); // 应该输出 false

        // 出队测试
        int element = queue.dequeue();
        System.out.println("出队元素: " + element); // 应该输出 1
        System.out.println("出队后队列: " + queue); // 应该输出 [2, 3, 4, 5]

        // 再入队一个元素
        queue.enqueue(6);
        System.out.println("再入队6后: " + queue); // 应该输出 [2, 3, 4, 5, 6]

        // 查看队头元素
        System.out.println("队头元素: " + queue.peek()); // 应该输出 2

        // 测试清空队列
        queue.clear();
        System.out.println("清空队列后: " + queue); // 应该输出 []
        System.out.println("队列是否为空: " + queue.isEmpty()); // 应该输出 true
    }
}
